#pragma once
#include <iostream>
#include <sstream>
#include <string>

#include "../functions.h"

// #define debug

void matrix() {
  const short operation =
      get_choice("Опции", {"Определитель", "Нахождение неизвестных"});
  stringstream stream_string;
  string segment;
  vector<vector<double>> matrix, a, b, x;
  vector<string> equations, equation, AX, B;
  double det;

  switch (operation) {
    case 1:
#ifdef debug
      stream_string = stringstream(get_rand_matrix(1000, 1000));
      clock_t start = clock();
#else
      stream_string = stringstream(
          input("Введите квадратную матрицу (без пробелов, элементы через "
                "запятые, строки через точки с запятой)"));
#endif

      while (getline(stream_string, segment, ';')) {
        vector<double> row;
        stringstream stream_row(segment);
        string item;

        while (getline(stream_row, item, ',')) row.push_back(stod(item));

        matrix.push_back(row);
      }

      for (vector<double> row : matrix) {
        for (double num : row) cout << num << " ";
        cout << endl;
      }

      det = solve_determinant(matrix);
      print_equation({get_greek_letter("Delta"), det});

#ifdef debug
      cout << endl << "Время: " << double(clock() - start) / CLOCKS_PER_SEC;
#endif

      break;
    case 2:
#ifdef debug
      stream_string = stringstream(get_rand_matrix(1000, 1000));
      start = clock();
#else
      stream_string =
          stringstream(input("Введите систему уравнений (без пробелов, строки "
                             "через точки с запятой)"));
#endif

// Парсинг системы уравнений в матрицы A и B (AX = B) и вектора X (неизвестные)
// с помощью функции parseEquations
#ifdef debug
      const parsed_equations = parseEquations(get_rand_matrix(1000, 1000));
#else
      auto parsed_equations = parseEquations(stream_string.str());
#endif

      vector<vector<double>> A = parsed_equations.first;
      vector<double> B = parsed_equations.second;

      // Проверка на то, что матрица A является квадратной
      if (A.size() != A[0].size()) {
        cout << "Матрица A не является квадратной" << endl;
        break;
      }

      // Проверка на то, что количество уравнений равно количеству неизвестных
      if (A.size() != B.size()) {
        cout << "Количество уравнений не равно количеству неизвестных" << endl;
        break;
      }

      // Вывод системы уравнений
      for (int i = 0; i < A.size(); i++) {
        for (int j = 0; j < A[i].size(); j++) {
          cout << A[i][j] << "x" << j + 1;
          if (j != A[i].size() - 1) cout << " + ";
        }
        cout << " = " << B[i] << endl;
      }

      // Количество уравнений
      int num_equations = A.size();

      // Решение системы уравнений с помощью метода Гаусса с исопльзование
      // функции solveGauss
      vector<double> X = solveGauss(A, B);

      // Вывод решения системы уравнений
      for (int i = 0; i < num_equations; i++) {
        cout << "x" << i + 1 << " = " << B[i] << endl;
      }

      cout << endl;

      break;
  }
}
